﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;

namespace Neitzel.Irc.Client
{
    /// <summary>
    /// Stores all Messages to a target
    /// </summary>
    public class MessageStore
    {
        #region fields

        /// <summary>
        /// Tracesource for all log messages.
        /// </summary>
        private static readonly TraceSource Logger = new TraceSource(IrcConstants.TraceSourceName);

        /// <summary>
        /// Message list for internal storage. Displayed as ReadOnlyCollection to the outside!
        /// </summary>
        private readonly List<DisplayMessage> _messages;

        #endregion

        #region Lifetime

        /// <summary>
        /// Initializes a new instance of the MessageStore class.
        /// </summary>
        public MessageStore()
        {
            MaxNumberOfMessages = Properties.Settings.Default.MaxNumberOfMessages;
            _messages = new List<DisplayMessage>();
        }

        /// <summary>
        /// Initializes a new instance of the MessageStore class.
        /// </summary>
        /// <param name="targetName">Name of the target we store messages for.</param>
        public MessageStore(string targetName)
            : this()
        {
            TargetName = targetName;
        }

        #endregion

        #region Events

        /// <summary>
        /// sdfds fdsfds.
        /// </summary>
        public event EventHandler<DisplayMessageEventArgs> NewMessageAdded;

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the name of the target we are storing messages for.
        /// </summary>
        public string TargetName { get; set; }

        /// <summary>
        /// Gets the list of IrcMessageFormats that arrived for this target.
        /// </summary>
        public ReadOnlyCollection<DisplayMessage> Messages => new ReadOnlyCollection<DisplayMessage>(_messages);

        /// <summary>
        /// Gets or sets the maximum number of stored messages.
        /// </summary>
        public int MaxNumberOfMessages { get; set; }

        /// <summary>
        /// Gets the max id of the message stored in this MessageStore.
        /// </summary>
        public int MaxId { get; private set; }

        #endregion

        #region Public Members

        /// <summary>
        /// Add a Message to the MessageStore
        /// </summary>
        /// <param name="message">DisplayMessage to store for this target</param>
        public void AddMessage(DisplayMessage message)
        {
            // validate
            if (message == null) throw new ArgumentNullException(nameof(message));
            
            // Increase MaxId and set Id of message
            MaxId++;
            message.Id = MaxId;

            // Add the Message to the 
            _messages.Add(message);

            // Check if we have to clean up
            while ((MaxNumberOfMessages > 0) && (_messages.Count > MaxNumberOfMessages))
            {
                // remove first message
                _messages.RemoveAt(0);
            }

            // Trigger the Event
            OnNewMessageAdded(new DisplayMessageEventArgs(message));
        }

        #endregion

        #region Protected Members

        /// <summary>
        /// Send the NewMessageAdded event.
        /// </summary>
        /// <param name="e">DisplayMessageEventArgs to send.</param>
        protected virtual void OnNewMessageAdded(DisplayMessageEventArgs e)
        {
            // Local copy to prevent race conditions
            var handler = NewMessageAdded;

            // raise the event
            handler?.Invoke(this, e);
        }

        #endregion
    }
}
